$TITLE ('RTX-51 ISR-FUNCTION HANDLING')
$SYMBOLS
$NOXREF
$NOCOND
$NOMOD51
$NORB
$PAGELENGTH(80) PAGEWIDTH(110)
;************************************************************************
;*									*
;*    R T X - 5 1  :   RTX-51 ISR-FUNCTION HANDLING                     *
;*							     		*
;*----------------------------------------------------------------------*
;*                                                                      *
;*    Filename     :   RTXIHAND.A51                                     *
;*    Language     :   Keil A-51                                        *
;*    Dev. system  :   Keil uVision2                                    *
;*    Targetsystem :   Any system based upon 8051 up                    *
;*                                                                      *
;*    Purpose      :   Implements the handling of the ISR-Functions     *
;*								     	*
;*----------------------------------------------------------------------*
;* Rev. |  Released   | Programmer    | Comments                        *
;*----------------------------------------------------------------------*
;* 0.1  |  20.6.91    | Th. Fischler  | First implementation for V4     *
;*      |  4.6.92     |               | RTXINS.INC converted to proc.   *
;* 5.00 | 12.10.1994  | E. Glatz      | SEM_DEQUEUE added               *
;*      | 15.02.1995  |               | Comments (no code changes)      *
;* 7.00 |  13.11.2001 | T. Mueller    | Release 7.00                    *
;************************************************************************
;*    Copyright 1991 .. 2001 METTLER  &  FUCHS  AG,  CH-8953 Dietikon   *
;************************************************************************

$INCLUDE (RTXIMASK.INC)
$INCLUDE (RTXDEBUG.INC)


;*----------------------------------------------------------------------*
;*	I M P O R T S
;*----------------------------------------------------------------------*

$INCLUDE (RTXCONST.INC)
$INCLUDE (RTXEXTRN.INC)

;        FROM RTXQUOP
EXTRN    CODE     (?RTX_TMO_DEQUEUE, ?RTX_INTSIG_DEQUEUE)
EXTRN    CODE     (?RTX_MSG_DEQUEUE, ?RTX_SEM_DEQUEUE)

;        FROM RTXINS
EXTRN    CODE     (?RTX_INSERT_RDY_PRIO)


;*----------------------------------------------------------------------*
;*	E X P O R T S
;*----------------------------------------------------------------------*

PUBLIC   ?RTX_HANDLE_ISR_SEND_SIG
PUBLIC   ?RTX_HANDLE_ISR_SEND_MES
PUBLIC   ?RTX_HANDLE_NF_CHECK_REQ


;*----------------------------------------------------------------------*
;*	P R O C E D U R E S
;*----------------------------------------------------------------------*

;*----------------------------------------------------------------------*
;*      H A N D L E _ I S R _ S E N D _ S I G
;*----------------------------------------------------------------------*
;*      Internal handling for sending a signal from an ISR to a task
;*----------------------------------------------------------------------*
;*      Input:   - R0 holds the user-task number
;*
;*      Output:  - Changes DPTR, ACC, R0, R2, ?RTX_TMP0, ?RTX_TMP1,
;*                 ?RTX_TMP2
;*                 ?RTX_REQ_REDISPATCH set, if task made ready
;*
;*      Task-Interrupts must be disabled on entry of this function !!
;*----------------------------------------------------------------------*

?RTX?HANDLE_ISR_SEND_SIG?RTXIHAND   SEGMENT CODE
                                    RSEG    ?RTX?HANDLE_ISR_SEND_SIG?RTXIHAND

?RTX_HANDLE_ISR_SEND_SIG:
               ; Evaluate the internal Task-Number
               MOV   DPH, #HIGH(?RTX_USER_NUM_TABLE)
               MOV   A, #LOW(?RTX_USER_NUM_TABLE)
               ADD   A, R0
               MOV   DPL, A
               ; DPTR -> user_num_table[user_num]
               MOVX  A, @DPTR
               CJNE  A, #NO_TASK, TASK_FOUND
               RET

TASK_FOUND:    MOV   R0, A                      ; internal task-num in R0
               MOV   DPH, #HIGH(?RTX_TID_TABLE)
               MOV   A, #LOW(?RTX_TID_TABLE)
               ADD   A, R0
               MOV   DPL, A                     ; DPTR-> TID_TABLE[task_num]
               MOVX  A, @DPTR

               ;  Set up ptr to task state of signal receiving task
               MOV   R2, A                      ; save TID of receiving task
               MOV   A, R0
               RL    A
               RL    A
               ADD   A, #LOW (?RTX_STATE_TABLE)
               MOV   DPL, A
               MOV   DPH, #HIGH(?RTX_STATE_TABLE)

               MOVX  A, @DPTR
;
;     Depending on the state of the signal receiving task one of the two
;     following actions is performed:
;     a) task waits for signal: task is made ready, req_redispatch is set
;        to true
;     b) task does not wait for signal: signal is stored as request in this
;        tasks first state byte, control is returned to caller
;
                                                ; Check if destination task
               JB    ACC.2, WAITS               ; is waiting for signal
                                                ; Check if already a signal was
                                                ; sent to this task, which it
               JB    ACC.7, PENDING             ; did not yet receive
                                           
;
;       Signal receiving task does not wait for it.
;
NO_PENDING_REQ:
               ORL   A, #80H                    ; Set signal request bit.
               MOVX  @DPTR, A                   ; Store it in first state byte
               RET

PENDING:       RET                              ; task had already
                                                ; a pending signal request

;
;       Signal receiving task waits for it.
;
WAITS:         MOV   ?RTX_TMP0, R2

               POP   ?RTX_TMP1                  ; Make free 2 bytes of stack
               POP   ?RTX_TMP2                  ; for subroutine call
               ; DPTR->state_table[task no]
               ; ?RTX_TMP0 contains task id
               CALL  ?RTX_TMO_DEQUEUE
               ; DPTR, ?RTX_TMP0 preserved
               CALL  ?RTX_INTSIG_DEQUEUE
               ; DPTR, ?RTX_TMP0 preserved
               CALL  ?RTX_MSG_DEQUEUE
               JZ    MSGDEQDONE                 ; Eval ret code if deq done
                                                ; DPTR preserved if no deq done
               CALL  ?RTX_SEM_DEQUEUE           ; ?RTX_TMP0 preserved
MSGDEQDONE:
               ; Store return status in con-
               ; text of signal receiving task
               MOV   A, R2
                                                ; Fast and standard task context
               JB    ACC.4, DRIV_CONTEXT        ; must be handled differently

               ; Store in standard task (=non driver task) context
               ANL   A, #0FH
               MOV   R0, A                      ; internal Task-number in R0
               MOV   A, #LOW(?RTX_KNTXT_PTR_TABLE)
               ADD   A, R0
               ADD   A, R0
               MOV   DPL, A
               MOV   DPH, #HIGH(?RTX_KNTXT_PTR_TABLE)
               MOVX  A, @DPTR
               MOV   R0, A
               INC   DPL
               MOVX  A, @DPTR
               MOV   DPH, R0
               MOV   DPL, A                     ; DPTR -> Task context
               MOV   A, #SIG_EVENT
               INC   DPL
               MOVX  @DPTR, A                   ; Store return status to r7

               ; Insert task in ready list and prepare function return
               MOV   A, R2
               JMP   COMMON

                                                ; Store in standard task context
DRIV_CONTEXT:  JB    ACC.1, DRIV3
               JB    ACC.0, DRIV2

               MOV   RB1R7, #SIG_EVENT          ; Store return status
               ; Insert task in ready list and prepare function return
               MOV   A, R2
               JMP   COMMON

DRIV2:         MOV   RB2R7, #SIG_EVENT
               ; Insert task in ready list and prepare function return
               MOV   A, R2
               JMP   COMMON

DRIV3:         MOV   RB3R7, #SIG_EVENT
               ; Insert task in ready list and prepare function return
               MOV   A, R2

COMMON:        ; Insert task in ready list
               CALL  ?RTX_INSERT_RDY_PRIO
               PUSH  ?RTX_TMP2                  ; Restore return address
               PUSH  ?RTX_TMP1                  ; to stack
               SETB  ?RTX_REQ_REDISPATCH
               RET


;*----------------------------------------------------------------------*
;*      H A N D L E _ I S R _ S E N D _ M E S
;*----------------------------------------------------------------------*
;*      Internal handling for sending a message from an ISR to a task
;*----------------------------------------------------------------------*
;*      Input:   - R0 : mailbox-number
;*               - R1 : HIGH(message)
;*               - R2 : LOW(message)
;*
;*      Output:  - Changes DPTR, ACC, R0, ?RTX_TMP0, ?RTX_TMP1,
;*                 ?RTX_TMP2
;*                 ?RTX_REQ_REDISPATCH set, if task made ready
;*
;*      Task-Interrupts must be disabled on entry of this function !!
;*----------------------------------------------------------------------*

?RTX?HANDLE_ISR_SEND_MES?RTXIHAND   SEGMENT CODE
                                    RSEG    ?RTX?HANDLE_ISR_SEND_MES?RTXIHAND

?RTX_HANDLE_ISR_SEND_MES:
               MOV   A, R0                      ; Get mailbox number param.
               SWAP  A
               RR    A                          ; ACC := 8 * mailbox nr.
               ADD   A, #LOW(?RTX_MBX_CONTROL_BASE)
               MOV   DPL, A
               MOV   DPH, #HIGH(?RTX_MBX_CONTROL_BASE) ; DPTR --> MBX#_COUNT
;
;       Depending on mbx-count values one of the following actions
;       is performed:
;       a) MBX#_COUNT < 0 (tasks are waiting for messages, MBX#_COUNT is 2's 
;          complement of waiting task count):
;          Pass message directly to first waiting task !
;       b) MBX#_COUNT = 8 (message list contains 8 messages, i.e. is full):
;          Message is lost !
;       c) MBX#_COUNT = 0..7 (no tasks wait for messages, message list is not
;          full):
;          Write message to mailbox message list !
;
               GLOBAL_INT_DISABLE
               MOVX  A, @DPTR                   ; Get MBX#_COUNT
               ; Check if any tasks are waiting for messages
               JB    ACC.7, TASKS_WAIT          ; Jump if tasks wait (count<0)
                                                ; Check if message list is
NO_TASKS_WAIT: JNB   ACC.3, NOT_FULL            ; full (max. 8 messages)
               GLOBAL_INT_ENABLE
               RET                              ; Return, message lost


;
;       No tasks wait for messages and message list is not full
;       (MBX#_COUNT = 0..7)
;
NOT_FULL:	                                
               INC   A                          ; MBX#_COUNT = MBX#_COUNT + 1
               MOVX  @DPTR, A                   ; Store new MBX#_COUNT value
               INC   DPL
               INC   DPL
               INC   DPL                        ; DPTR --> MBX#_LAST

               MOVX  A, @DPTR                   ; MBX#_LAST = MBX#_LAST + 1
               INC   A
               ANL   A, #0EFH

               MOV   R0, DPL                    ; save DPL
               MOV   DPH, #HIGH(?RTX_MBX_PAGE)
               MOV   DPL, A                     ; DPTR: FIFO-Pointer to last
                                                ; el. + 1 of MBX#_LIST
               MOV   A, R1                      ; Insert high (R1) and low (R2)
               MOVX  @DPTR, A                   ; byte of msg.(high byte first)
					        ; in specified mailbox.
               MOV   A, DPL                     ; Increment FIFO-pointer
               INC   A
               ANL   A, #0EFH
               MOV   DPH, #HIGH(?RTX_MBX_CONTROL_BASE)
               MOV   DPL, R0
               MOVX  @DPTR, A                   ; Store new value of LAST-ptr
                                                ; (Points always to LAST
                                                ;  element)
               MOV   DPL, A
               MOV   DPH, #HIGH(?RTX_MBX_PAGE)
               MOV   A, R2
               MOVX  @DPTR, A
               GLOBAL_INT_ENABLE
               RET                              ; Message written to mbx


;       At least one task is waiting for a message: do not write message to
;       mailbox list but pass it directly to waiting task.
;       (MBX#_COUNT < 0)
;       
TASKS_WAIT:    ; Dequeue first waiting task from mailbox task list
               INC   A
               MOVX  @DPTR, A                   ; MBX#_COUNT=MBX#_COUNT+1
               INC   DPL                        ; (dec. 2's compl. means incr.)
               INC   DPL                        ; DPTR --> MBX#_FIRST
               MOVX  A, @DPTR
               MOV   R0, A                      ; temp. save MBX#_FIRST
               INC   A
               ANL   A, #0EFH
               MOVX  @DPTR, A                   ; MBX#_FIRST=MBX#_FIRST+1

               MOV   DPH, #HIGH(?RTX_MBX_PAGE)
               MOV   DPL, R0                    ; (DPTR) --> task FIFO
               MOVX  A, @DPTR                   ; Read first task id from list
               MOV   ?RTX_TMP0, A               ; and store in ?RTX_TMP0
               GLOBAL_INT_ENABLE

               ; Set up pointer to state_table[task no]
               ANL   A, #01FH
               RL    A
               RL    A
               ADD   A, #LOW(?RTX_STATE_TABLE)
               MOV   DPH, #HIGH(?RTX_STATE_TABLE)
               MOV   DPL, A                     ; DPTR->state_table[task no]
               MOVX  A, @DPTR
               ANL   A, #0FEH                   ; Reset msg wait bit in state
               MOVX  @DPTR, A

               ; Dequeue task from any wait list it could be contained in
               POP   ?RTX_TMP1                  ; Make free 2 bytes of stack
               POP   ?RTX_TMP2                  ; for subroutine call
                                                ; DPTR->state_table[task no]
                                                ; ?RTX_TMP0 contains task id
               CALL ?RTX_TMO_DEQUEUE
                                                ; DPTR, ?RTX_TMP0 preserved
               CALL ?RTX_INTSIG_DEQUEUE

               ; Return status and message have to be stored in this
               ; tasks context
               MOV   A, ?RTX_TMP0               ; Fast task context must be
               JB    ACC.4, DRIVER_CONTEXT      ; handled differently

               ; Store in standard task (=non driver task) context
               ANL   A, #0FH                    ; ACC := standard task nr.
               MOV   R0, A
               MOV   A, #LOW(?RTX_KNTXT_PTR_TABLE)
               ADD   A, R0
               ADD   A, R0
               MOV   DPL, A
               MOV   DPH, #HIGH(?RTX_KNTXT_PTR_TABLE) ; DPTR -> tasks context
               MOVX  A, @DPTR
               MOV   R0, A
               INC   DPL
               MOVX  A, @DPTR
               MOV   DPH, R0
               MOV   DPL, A

               MOV   A, #MSG_EVENT
               INC   DPL
               MOVX  @DPTR, A                   ; Store return status to r7

               ; Set up pointer to message return location (it is
               ; contained in context R5/R6)
               INC   DPL                        ; DPTR --> context (R6)
               MOVX  A, @DPTR                   ; Get R6
               MOV   R0, A
               INC   DPTR                       ; DPTR --> context (R5)
               MOVX  A, @DPTR                   ; Get R5
               MOV   DPH, A
               MOV   DPL, R0                    ; (DPTR)-->msg return location
               JMP   STORE_MSG

               ; Store in fast task (=driver task) context
DRIVER_CONTEXT:
               JB    ACC.1, DRIVER3
               JB    ACC.0, DRIVER2

DRIVER1:       MOV   RB1R7, #MSG_EVENT          ; Store return status
               ; Set up pointer to message
               MOV   DPH, RB1R5                 ; return location (it is con-
               MOV   DPL, RB1R6                 ; tained in context R5/R6)
               JMP   STORE_MSG

DRIVER2:       MOV   RB2R7, #MSG_EVENT          ; Store return status
               ; Set up pointer to message
               MOV   DPH, RB2R5                 ; return location (it is con-
               MOV   DPL, RB2R6                 ; tained in context R5/R6)
               JMP   STORE_MSG

DRIVER3:       MOV   RB3R7, #MSG_EVENT          ; Store return status
               ; Set up pointer to message
               MOV   DPH, RB3R5                 ; return location (it is con-
               MOV   DPL, RB3R6                 ; tained in context R5/R6)

STORE_MSG:     ; Now store message at return location in external RAM
               MOV   A, R1
               MOVX  @DPTR, A                   ; Store HIGH(MESSAGE)
               INC   DPTR
               MOV   A, R2
               MOVX  @DPTR, A                   ; Store LOW(MESSAGE)

               MOV   A, ?RTX_TMP0               ; Restore dest. task id.

               ; Insert task in ready list
                                                
INSERT_PRIO:   CALL  ?RTX_INSERT_RDY_PRIO
               PUSH  ?RTX_TMP2                  ; Restore return address
               PUSH  ?RTX_TMP1                  ; to stack

               SETB  ?RTX_REQ_REDISPATCH
               RET



;*----------------------------------------------------------------------*
;*      H A N D L E _ N F _ C H E C K _ R E Q
;*----------------------------------------------------------------------*
;*      Internal handling for checking non-full wait tasks
;*----------------------------------------------------------------------*
;*      Input:   - R0 : mailbox-number
;*
;*      Output:  - Changes DPTR, ACC, R0, ?RTX_TMP0, ?RTX_TMP1,
;*                 ?RTX_TMP2
;*                 ?RTX_REQ_REDISPATCH set, if task made ready
;*
;*      Task-Interrupts must be disabled on entry of this function !!
;*----------------------------------------------------------------------*

?RTX?HANDLE_NF_CHECK_REQ?RTXIHAND   SEGMENT CODE
                                    RSEG    ?RTX?HANDLE_NF_CHECK_REQ?RTXIHAND

?RTX_HANDLE_NF_CHECK_REQ:
               MOV   A, R0                      ; Get mailbox number param.
               SWAP  A
               RR    A                          ; ACC := 8 * mailbox nr.
               ADD   A, #LOW(?RTX_MBX_CONTROL_BASE)
               MOV   DPL, A
               MOV   DPH, #HIGH(?RTX_MBX_CONTROL_BASE)
               INC   DPL                        ; DPTR --> MBX#_TCOUNT


               ; Check if any tasks wait for non full message list
	       MOVX  A, @DPTR
	       JNZ   TWAIT			; Jump if MBX#_TCOUNT > 0
               RET

	       ; Dequeue first non full wait task from nf wait list
TWAIT:	       DEC   A
	       MOVX  @DPTR, A			; MBX#_TCOUNT=MBX#_TCOUNT-1
	       INC   DPL
	       INC   DPL
	       INC   DPL
               MOV   R0, DPL
	       MOVX  A, @DPTR
	       ; (DPTR) --> nf wait FIFO
	       MOV   DPL, A
               MOV   DPH, #HIGH(?RTX_MBX_PAGE)
	       MOVX  A, @DPTR			; Get task id
               MOV   ?RTX_TMP0, A               ; Save task id in ?RTX_TMP0
	       ; Increment FIFO pointer
	       MOV   A, DPL
	       ANL   A, #00FH			; Check if at end of FIFO
	       CJNE  A, #00FH, NO_WRAP
	       MOV   A, DPL			; Get back old ptr value
	       ANL   A, #0F0H			; Rewind ptr to FIFO start
	       JMP   INC_DONE
NO_WRAP:       MOV   A, DPL			; Get back old ptr value
	       INC   A				; Just inc., not at buffer end
INC_DONE:      MOV   DPL, R0
               MOV   DPH, #HIGH(?RTX_MBX_CONTROL_BASE)
	       MOVX  @DPTR, A			; MBX#_TFIRST=MBX#_TFIRST+1

	       ; Set up ptr to task state
               MOV   A, ?RTX_TMP0
	       ANL   A, #01FH
	       RL    A
	       RL    A
               ADD   A, #LOW (?RTX_STATE_TABLE)
	       MOV   DPL, A
               MOV   DPH, #HIGH (?RTX_STATE_TABLE) ; DPTR-->state_table[task_no]
               POP   ?RTX_TMP1                  ; Make free 2 bytes of stack
               POP   ?RTX_TMP2                  ; for subroutine call
                                                ; DPTR->state_table[task no]
                                                ; ?RTX_TMP0 contains task id
               CALL ?RTX_TMO_DEQUEUE

	       ; Reset nf wait bit
	       INC   DPL
	       MOVX  A, @DPTR			; Get second task state byte
	       ANL   A, #07FH			; Clear WN bit
	       MOVX  @DPTR, A			; Store second task state byte

	       ; Store return status in con text of non full wait task
	       ; Fast and standard task context must be handled differently
               MOV   A, ?RTX_TMP0
               JB    ACC.4, DRIV_CONT

	       ; Store in standard task context
	       ANL   A, #0FH
               MOV   R0, A
               MOV   A, #LOW(?RTX_KNTXT_PTR_TABLE)
               ADD   A, R0
               ADD   A, R0
	       MOV   DPL, A
               MOV   DPH, #HIGH(?RTX_KNTXT_PTR_TABLE)
	       MOVX  A, @DPTR
               MOV   R0, A
	       INC   DPL
	       MOVX  A, @DPTR
               MOV   DPH, R0
	       MOV   DPL, A
	       MOV   A, #NFL_EVENT
	       INC   DPL
	       MOVX  @DPTR, A			; Store return status
	       JMP   MAKE_RDY

	       ; Store in fast task context
DRIV_CONT:     JB    ACC.1, DRV3
               JB    ACC.0, DRV2

	       MOV   RB1R7, #NFL_EVENT		; Store return status
	       JMP   MAKE_RDY

DRV2:          MOV   RB2R7, #NFL_EVENT
	       JMP   MAKE_RDY

DRV3:          MOV   RB3R7, #NFL_EVENT

MAKE_RDY:      ; Insert task in ready list
               MOV   A, ?RTX_TMP0
               CALL  ?RTX_INSERT_RDY_PRIO
               PUSH  ?RTX_TMP2                  ; Restore return address
               PUSH  ?RTX_TMP1                  ; to stack

               SETB  ?RTX_REQ_REDISPATCH
               RET


;
;   END OF MODULE
;
	END


